import router from "@/router/index.js";
import store from "@/store";
import NProgress from "nprogress"; // progress bar
import "./progress.css";
import { getToken, getUserName } from "@/utils/auth"; // getToken from cookie
import _ from "lodash";

const { initSettings, getSetting, getSettings, getSettingBool } = window.systemParamsUtils;

NProgress.configure({ showSpinner: false }); // NProgress Configuration

// 合并白名单列表
const WHITE_LIST = getSetting("WHITE_LIST");
let whiteList = ["/login", "/auth-redirect"]; // no redirect whitelist
if (WHITE_LIST instanceof Array) {
  whiteList = whiteList.concat(WHITE_LIST);
}

router.beforeEach((to, from, next) => {
  NProgress.start(); // start progress bar
  let queryObject = getQueryObject();
  if (_.isEmpty(getSettings())) {
    initSettings().then(() => location.reload()); // 如果配置信息为空，则先加载配置信息
  } else if (!getSettingBool("NEED_LOGIN")) {
    noNeedLogin(to, from, next); // 如果项目不需要登录，则不需要获取用户信息和权限
  } else if (getSettingBool("IS_OAUTH2") && queryObject.code) {
    getAccessToken(queryObject); // 如果使用oauth2登录并且地址栏中有code参数，则去请求token
  } else {
    checkLogin(to, next); // 检查是否登录
  }
});

/**
 * 将url的参数转为对象
 * 不传默认获取当前浏览器地址的参数
 */
function getQueryObject(url = window.location.href) {
  const search = url.substring(url.lastIndexOf("?") + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}

// permission judge function
function hasPermission(userPermissions = [], routePermissions = []) {
  if (routePermissions && routePermissions.length === 0) {
    return true;
  }
  return userPermissions.some(userPermission => {
    return routePermissions.indexOf(userPermission) >= 0;
  });
}

router.afterEach(() => {
  NProgress.done(); // finish progress bar
});

/**
 * 不需要登录则直接加载所有路由
 * @param to
 * @param from
 * @param next
 */
function noNeedLogin(to, from, next) {
  if (store.getters.addRouters.length === 0) {
    generateRoutes([], next, to);
  } else {
    next();
  }
}

/**
 * 如果是Oauth2登录并且地址栏上有code字段，则去请求access_token
 * @param queryObject   地址栏上的参数
 */
async function getAccessToken(queryObject) {
  let code = queryObject.code.split("#/")[0];
  try {
    await store.dispatch("GetOAuthToken", { code });
    if (getToken()) {
      window.location.href = "http://" + window.location.host + decodeURIComponent(window.location.pathname);
    }
  } catch (reason) {
    console.error(reason);
    store.dispatch("FedLogout").then(() => {
      location.reload();
    });
  }
}

/**
 * 检查是否在白名单中,进行页面跳转
 * @param to
 * @param next
 * @param link
 */
function checkIsInWhiteList(to, next, link, result) {
  if (whiteList.indexOf(to.path) !== -1) {
    next(); // 在免登录白名单，直接进入
  } else if (result instanceof Promise) {
    result.then(result => {
      if (result && result.status === 403 && result.link) {
        console.error("oauth2验证不通过，将跳转到登录页");
      }
    });
  } else {
    !link && next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
    NProgress.done(); // if current page is login will not trigger afterEach hook, so manually handle it
  }
}

/**
 * 生成路由
 * @param permissions   用户权限
 * @param next
 * @param to
 */
function generateRoutes(permissions, next, to) {
  store.dispatch("GenerateRoutes", { permissions }).then(() => {
    
    // 根据权限生成可访问的路由表
    router.addRoutes(store.getters.addRouters); // 动态添加可访问路由表
   
    if (hasPermission(store.getters.permissions, to.meta.permission)) {
      next({ ...to, replace: true });
    } else {
      next({
        path: "/",
        replace: true
      });
    }
    // next({ ...to, replace: true }); // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
  });
}

function checkLogin(to, next) {
  if (getUserName()) {
    if (to.path === "/login") {
      next({ path: "/" });
      NProgress.done(); // if current page is dashboard will not trigger	afterEach hook, so manually handle it
    } else {
      let permissionsLength = store.getters.permissions.length;
      if (!store.getters.name && !permissionsLength) {
        try {
          // 获取用户信息
          // await ;
          store.dispatch("GetUserInfo").then(() => {
            store.dispatch("QueryCurrenDmDeptInfo");

            let permissions = store.getters.permissions;
            generateRoutes(permissions, next, to);
          });
        } catch (err) {
          store.dispatch("FedLogout").then(() => {
            if (!err.link) {
              next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
            } else {
              next({ path: "/" });
            }
          });
          // await store.dispatch("FedLogout")   // 如果获取用户信息失败，则将本地的用户信息相关的东西清空，并登出
          // if (!err.link) {
          //     next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
          // } else {
          //     next({ path: "/" });
          // }
        }
      } else {
        // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
        // if (hasPermission(store.getters.permissions, to.meta.permission)) {
        // next();
        // } else {
        //     next({
        //         path: "/403",
        //         replace: true,
        //         query: { noGoBack: true }
        //     });
        // }
        const permissionRouters = store.getters.permission_routers;
        // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
        if (hasPermission(store.getters.permissions, to.meta.permission)) {
          next();
          NProgress.done();
          return;
        }
        if (Array.isArray(permissionRouters) && permissionRouters.length) {
          next({
            name: permissionRouters[0].name
          });
          NProgress.done();
          return;
        }
        next({
          path: "/403",
          replace: true,
          query: {
            noGoBack: true
          }
        });
        NProgress.done();
      }
    }
  } else {
    if (getSetting("BASE_API") === "/easy-mock") {
      checkIsInWhiteList(to, next); // 检查是否在白名单中
    } else {
      try {
        store.dispatch("GetUserInfo").then(() => {
         store.dispatch("QueryCurrenDmDeptInfo");

          window.location.reload();
        });
        // await store.dispatch("GetUserInfo")
        // window.location.reload();
      } catch (result) {
        let link;
        result && (link = result.link);

        checkIsInWhiteList(to, next, link, result); // 检查是否在白名单中
      }
    }
  }
}
